/******************************************************************************
 *  Copyright 2013 Bernhard Grünewaldt                                        *
 *                                                                            *
 *  Licensed under the Apache License, Version 2.0 (the "License");           *
 *  you may not use this file except in compliance with the License.          *
 *  You may obtain a copy of the License at                                   *
 *                                                                            *
 *      http://www.apache.org/licenses/LICENSE-2.0                            *
 *                                                                            *
 *  Unless required by applicable law or agreed to in writing, software       *
 *  distributed under the License is distributed on an "AS IS" BASIS,         *
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
 *  See the License for the specific language governing permissions and       *
 *  limitations under the License.                                            *
 ******************************************************************************/
package com.google.code.greenwood.confluencemavenreleaseinfomacro.parser;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.google.code.greenwood.confluencemavenreleaseinfomacro.pojo.ArtifactInformation;
import com.google.code.greenwood.confluencemavenreleaseinfomacro.pojo.ModuleReleaseVersion;
import com.google.code.greenwood.confluencemavenreleaseinfomacro.pojo.Properties;
import com.google.code.greenwood.confluencemavenreleaseinfomacro.pojo.ReleaseInformation;

public class DomDocumentToReleaseInfoParser {

	private static final Logger log = LoggerFactory.getLogger(DomDocumentToReleaseInfoParser.class);
	
	public ReleaseInformation parsePomFilesRecursive(File pomXmlFile, Boolean parseModules) throws IOException, ParserConfigurationException , SAXException {
	    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
	    DocumentBuilder builder = factory.newDocumentBuilder();
	    Document document = builder.parse( pomXmlFile );
	    
	    ReleaseInformation info = new ReleaseInformation();
	    
	    // first container is <project ...>
	    if (document.getFirstChild().getNodeName().equals("project")) {
	    	NodeList nodelist = document.getFirstChild().getChildNodes();
	    	
	    	for (int i=0;i<nodelist.getLength();i++) {
	    		if (nodelist.item(i).getNodeType() == 1) {	    			
	    			// Parse Parent Pom
	    			if (nodelist.item(i).getNodeName().equals("groupId")) {
	    				info.setGroupid(nodelist.item(i).getTextContent());
	    			}
	    			if (nodelist.item(i).getNodeName().equals("artifactId")) {
	    				info.setArtifactid(nodelist.item(i).getTextContent());
	    			}
	    			if (nodelist.item(i).getNodeName().equals("name")) {
	    				info.setName(nodelist.item(i).getTextContent());
	    			}
	    			if (nodelist.item(i).getNodeName().equals("version")) {
	    				info.setVersion(nodelist.item(i).getTextContent());	
	    			}
	    			
	    			// Parse Modules
	    			if (nodelist.item(i).getNodeName().equals("modules")) {
	    				NodeList moduleNodes = nodelist.item(i).getChildNodes();
	    				ArrayList<String> modules = new ArrayList<String>();
	    				for (int j=0;j<moduleNodes.getLength();j++){
	    					if (moduleNodes.item(j).getNodeType() == 1) {
	    						modules.add(moduleNodes.item(j).getTextContent()); 
	    					}
	    				}
	    				if (parseModules == true) {
	    					log.debug("parseModules = False");
	    					info.addModules(parseModules(pomXmlFile, modules));
	    				} else {
	    					log.debug("parseModules = True");
	    					Collection<ModuleReleaseVersion> moduelVersions = new ArrayList<ModuleReleaseVersion>();
	    					for (String mod : modules) {
	    						ModuleReleaseVersion vers = new ModuleReleaseVersion();
	    						vers.setName(mod);
	    						moduelVersions.add(vers);
	    					}
	    					info.addModules(moduelVersions);
	    				}
	    			}
	    			
    			
	    		}
	    	}
	    	
	    }
	    return info;
	}
	
	public Collection<ModuleReleaseVersion> parseModules(File parentPomXmlFile, ArrayList<String> modules) throws IOException, ParserConfigurationException , SAXException {
		Collection<ModuleReleaseVersion> modversions = new ArrayList<ModuleReleaseVersion>();
		for (String modulename : modules) {
			String moduleFilename = getModuleFilenameFromParentPomAndModuleName(parentPomXmlFile, modulename);
			log.debug("parsing ModuleFilename: {}", moduleFilename);
			//System.out.println("--"+moduleFilename + "--" + new File(moduleFilename).exists());
		    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		    DocumentBuilder builder = factory.newDocumentBuilder();
		    File modulefile = new File(moduleFilename); 
		    Document document = builder.parse(modulefile);
		    
		    ModuleReleaseVersion modVersion = new ModuleReleaseVersion();
		    
		    Collection<ArtifactInformation> ainfos = new ArrayList<ArtifactInformation>();
		    Collection<Properties> propertyList = new ArrayList<Properties>();

		    // first container is <project ...>
		    if (document.getFirstChild().getNodeName().equals("project")) {
		    	NodeList nodelist = document.getFirstChild().getChildNodes();
		    	
		    	// Properties
			    NodeList properties = findChildNodesByName("properties", nodelist);
			    if (properties != null) {
				   	for (int i=0;i<properties.getLength();i++) {
				   		if (properties.item(i).getNodeType() == 1) {
				   			Node propNode = properties.item(i);
				   			Properties prop = new Properties();
				   			prop.setPropertyName(propNode.getNodeName());
				   			prop.setPropertyValue(propNode.getTextContent());
				   			propertyList.add(prop);
				   		}
				   	}
			    }
			   			
			    	
		    	// Dependencies
		    	NodeList dependencies = findChildNodesByName("dependencies", nodelist);
		    	if (dependencies != null) {
			    	for (int i=0;i<dependencies.getLength();i++) {
			    		if (dependencies.item(i).getNodeType() == 1) {	   
			    			ArtifactInformation ainfo = new ArtifactInformation();
					    	for (int j=0;j<dependencies.item(i).getChildNodes().getLength();j++) {
					    		if (dependencies.item(i).getChildNodes().item(j).getNodeType() == 1) {	 
					    			
					    			if (dependencies.item(i).getChildNodes().item(j).getNodeName().equals("groupId")) {
					    				ainfo.setGroupid(dependencies.item(i).getChildNodes().item(j).getTextContent());
					    			}
					    			if (dependencies.item(i).getChildNodes().item(j).getNodeName().equals("artifactId")) {
					    				ainfo.setArtifactid(dependencies.item(i).getChildNodes().item(j).getTextContent());
					    			}
					    			if (dependencies.item(i).getChildNodes().item(j).getNodeName().equals("name")) {
					    				ainfo.setName(dependencies.item(i).getChildNodes().item(j).getTextContent());
					    			}
					    			if (dependencies.item(i).getChildNodes().item(j).getNodeName().equals("version")) {
					    				ainfo.setVersion(dependencies.item(i).getChildNodes().item(j).getTextContent());	
					    			}
					    			if (dependencies.item(i).getChildNodes().item(j).getNodeName().equals("type")) {
					    				ainfo.setPackaging(dependencies.item(i).getChildNodes().item(j).getTextContent());	
					    			}
					    		}
					    	}
					    	ainfos.add(ainfo);
			    		}
			    	}
		    	}
		    }
			modVersion.setProperties(propertyList);
		    modVersion.setDependencies(ainfos);
		    modVersion.setName(modulename);
		    modversions.add(modVersion);
		}		
		return modversions;
	}
	
	
	private NodeList findChildNodesByName(String nodename, NodeList nodelist) {
    	for (int i=0;i<nodelist.getLength();i++) {	
			if (nodelist.item(i).getNodeType() == 1) {	   
				if (nodelist.item(i).getNodeName().equals(nodename)) {
					return nodelist.item(i).getChildNodes();
				}
			}
    	}
    	return null;
	}
	
	public String getModuleFilenameFromParentPomAndModuleName(File parentPomXmlFile, String modulename) {
		String file = parentPomXmlFile.getParent()+System.getProperty("file.separator")+modulename+System.getProperty("file.separator")+"pom.xml";
		return file;
	}
}
